#ifndef TOOLS_H
#define TOOLS_H
#include <mutex>
#include <condition_variable>
#include <deque>
#include <queue>
#include <assert.h>
using namespace std;
typedef unique_lock<mutex> Lock;
struct FrameInfo{
	unsigned char * mask;
	unsigned short * coordinate; 
	unsigned char * spe_data;
	unsigned char * rgb_data;
};

struct FrameData {
	unsigned char * spe_data;
	unsigned char * rgb_data;
};

struct RawInfo
{
	int RAW_rows = 2048;
	int RAW_cols = 2048;
	int DMD_rows = 1140;
	int DMD_cols = 912;
	int OUT_rows = 1120;
	int OUT_cols = 880;
	//int window_size = 80;
	int window_width = 80;
	int window_higth = 80;
	int know_point_number = 40;
	int know_point_number_all = 6160;
	int channel = 30;
	int s_rows = 200;
	int s_cows = 320;
	int merged_rows = 550;
	int merged_cols = 1020;
};

template<class T>
class BlockQueue {
private:
	mutex m_mutex;
	condition_variable notfull;
	condition_variable notempty;

	deque<T> m_list;

	const int cap;
	bool hasCapacity() const
	{
		return cap > 0;
	}
public:
	explicit BlockQueue(const int _cap = 50) :cap(_cap) {}

	void push(const T & in) {
		Lock lk(m_mutex);
		if (hasCapacity() == true) {
			while (m_list.size() >= cap) {
				notfull.wait(lk);
			}
			m_list.push_back(in);
			notempty.notify_all();
		}
	}

	T pop() {
		Lock lk(m_mutex);
		while (m_list.empty()) {
			notempty.wait(lk);
		}
		T tem = *m_list.begin();
		m_list.pop_front();
		notfull.notify_all();
		return tem;
	}


	bool empty()
	{
		Lock lk(m_mutex);
		return m_list.empty();
	}

	bool full()
	{
		if (false == hasCapacity())
		{
			return false;
		}

		Lock lk(m_mutex);
		return m_list.size() >= cap;
	}

	int size() {
		Lock lk(m_mutex);
		return m_list.size();
	}
};



#endif

